package com.sma.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import com.sma.pojo.Role;
import com.sma.service.RoleService;
import com.sma.vo.RoleParams;

/**
 * 参数处理控制器，负责处理各种请求参数的场景，包括路径变量、请求体、请求参数等的不同组合。
 */
@Controller
@RequestMapping("/params")
public class ParamsController {

    @Autowired
    private RoleService roleService;

    /**
     * 首页请求处理方法，返回角色管理页面。
     * 在Spring MVC框架中，ModelAndView类的构造函数接受两个参数
     * 第一个参数通常是视图的逻辑名称。在这个例子中，"role"就是视图的逻辑名称
     * 虽然没有直接指出.jsp，但根据Spring MVC的默认配置和约定
     * 它会将这个逻辑名称解析为一个JSP文件，即系统会查找名为role.jsp的视图模板来渲染响应
     * 因此，这个方法确实隐式地定位了一个JSP视图，用于呈现给用户
     * @return 视图模型，指向角色页面。
     */
    @RequestMapping("/index")
    public ModelAndView index() {
        return new ModelAndView("role");
    }

    /**
     * 首页请求处理方法的另一种形式，返回角色管理页面的字符串路径。
     * @return 角色页面的字符串路径。
     */
    @RequestMapping("/index2")
    public String index2() {
        return "role";
    }

    /**
     * 处理带有普通请求参数的请求，演示如何获取和使用这些参数。
     * @param roleName 角色名称参数
     * @param note 备注参数
     * @return 视图模型，用于重定向或显示结果。
     */
    @RequestMapping("/common")
    public ModelAndView commonParams(String roleName, String note) {
        // 简单演示如何使用参数
        System.out.println("roleName =>" + roleName);
        System.out.println("note =>" + note);
        ModelAndView mv = new ModelAndView();
        mv.setViewName("index");
        return mv;
    }

    /**
     * 通过POJO对象接收请求体中的参数，便于处理复杂或多个参数的情况。
     * @param roleParams 包含角色参数和备注的VO对象
     * @return 视图模型，用于显示结果或进行重定向。
     */
    @RequestMapping("/common/pojo")
    public ModelAndView commonParamPojo(RoleParams roleParams) {
        // 使用POJO对象获取参数
        System.out.println("roleName =>" + roleParams.getRoleName());
        System.out.println("note =>" + roleParams.getNote());
        ModelAndView mv = new ModelAndView();
        mv.setViewName("index");
        return mv;
    }

    /**
     * 处理使用@RequestParam注解的请求参数，可以指定参数名称和是否必须。
     * @param roleName 角色名称请求参数
     * @param note 备注请求参数
     * @return 视图模型，用于显示结果或进行重定向。
     */
    @RequestMapping("/request")
    public ModelAndView requestParam(@RequestParam(value = "role_name", required = false) String roleName, String note) {
        // 使用@RequestParam注解获取参数
        System.out.println("roleName =>" + roleName);
        System.out.println("note =>" + note);
        ModelAndView mv = new ModelAndView();
        mv.setViewName("index");
        return mv;
    }

    /**
     * 通过路径变量获取URL中指定的id值，用于展示或操作特定ID的角色。
     * @param id 角色的ID，从URL路径中获取
     * @return 视图模型，包含角色信息的JSON视图。
     */
    @RequestMapping("/role/{id}")
    public ModelAndView pathVariable(@PathVariable("id") Long id) {
        Role role = roleService.getRole(id);
        ModelAndView mv = new ModelAndView();
        mv.addObject(role);
        mv.setView(new MappingJackson2JsonView());
        return mv;
    }

    /**
     * 使用@RequestBody注解从请求体中接收整个对象，适用于POST等提交复杂数据的场景。
     * @param roleParams 包含搜索条件的VO对象
     * @return 视图模型，包含搜索结果的JSON视图。
     */
    @RequestMapping(value = "/roles", method = RequestMethod.POST)
    public ModelAndView findRoles(@RequestBody RoleParams roleParams) {
        List<Role> roleList = roleService.findRoles(roleParams);
        ModelAndView mv = new ModelAndView();
        mv.addObject("roleList", roleList);
        mv.setView(new MappingJackson2JsonView());
        return mv;
    }

    /**
     * 删除角色，通过请求体接收一个角色ID列表，进行批量删除操作。
     * @param idList 角色ID列表，用于删除多个角色
     * @return 视图模型，包含删除总数的JSON视图。
     */
    @RequestMapping(value = "/remove/roles", method = RequestMethod.POST)
    public ModelAndView removeRoles(@RequestBody List<Long> idList) {
        ModelAndView mv = new ModelAndView();
        int total = roleService.deleteRoles(idList);
        mv.addObject("total", total);
        mv.setView(new MappingJackson2JsonView());
        return mv;
    }

    /**
     * 新增角色，通过请求体接收一个角色列表，进行批量插入操作。
     * @param roleList 角色列表，用于批量插入新角色
     * @return 视图模型，包含插入总数的JSON视图。
     */
    @RequestMapping(value = "/insert/roles", method = RequestMethod.POST)
    public ModelAndView insertRoles(@RequestBody List<Role> roleList) {
        ModelAndView mv = new ModelAndView();
        int total = roleService.insertRoles(roleList);
        mv.addObject("total", total);
        mv.setView(new MappingJackson2JsonView());
        return mv;
    }

    /**
     * 处理序列化参数的请求，展示如何接收和处理通过@RequestParam注解的序列化参数。
     * @param roleName 角色名称请求参数
     * @param note 备注请求参数
     * @return 视图模型，包含序列化参数的JSON视图。
     */
    @RequestMapping(value = "/serialize/params", method = RequestMethod.POST)
    public ModelAndView serializeParams(@RequestParam("roleName") String roleName, @RequestParam("note") String note) {
        ModelAndView mv = new ModelAndView();
        mv.setView(new MappingJackson2JsonView());
        mv.addObject("roleName", roleName);
        mv.addObject("note", note);
        return mv;
    }

    /**
     * 展示特定角色的JSON信息，通过路径变量获取角色ID。
     * @param id 角色ID
     * @param roleName 角色名称
     * @param note 角色备注
     * @return 视图模型，包含角色信息的JSON视图。
     */
    @RequestMapping("/role/info")
    public ModelAndView showRoleJsonInfo(Long id, String roleName, String note) {
        ModelAndView mv = new ModelAndView();
        mv.setView(new MappingJackson2JsonView());
        mv.addObject("id", id);
        mv.addObject("roleName", roleName);
        mv.addObject("note", note);
        return mv;
    }

    /**
     * 插入角色并重定向到角色信息页面，展示如何在插入后获取并使用新角色的ID。
     * @param model Spring的Model接口，用于向视图传递数据
     * @param roleName 角色名称
     * @param note 角色备注
     * @return 重定向到角色信息页面的字符串路径。
     */
    @RequestMapping("/role/insert")
    public String insertRole(Model model, String roleName, String note) {
        Role role = new Role();
        role.setRoleName(roleName);
        role.setNote(note);
        roleService.insertRole(role);
        model.addAttribute("roleName", roleName);
        model.addAttribute("note", note);
        model.addAttribute("id", role.getId());
        return "redirect:./info";
    }

    /**
     * 另一种插入角色的方法，使用ModelAndView对象进行重定向并传递数据。
     * @param mv ModelAndView对象，用于设置重定向视图和附加数据
     * @param roleName 角色名称
     * @param note 角色备注
     * @return 视图模型，用于重定向到角色信息页面。
     */
    @RequestMapping("/role/insert2")
    public ModelAndView insertRole2(ModelAndView mv, String roleName, String note) {
        Role role = new Role();
        role.setRoleName(roleName);
        role.setNote(note);
        roleService.insertRole(role);
        mv.setViewName("redirect:./info");
        mv.addObject("roleName", roleName);
        mv.addObject("note", note);
        mv.addObject("id", role.getId());
        return mv;
    }

    /**
     * 通过角色信息展示JSON格式的数据。
     * 此方法处理请求的URL路径为/role/info2，旨在返回一个包含角色信息的JSON对象。
     * 使用MappingJackson2JsonView将模型对象转换为JSON格式，以便在客户端如JavaScript中使用。
     * @param role 角色对象，包含需要展示的角色信息。
     * @return ModelAndView 对象，配置了JSON视图和角色对象。
     */
    @RequestMapping("/role/info2")
    public ModelAndView showRoleJsonInfo2(Role role) {
        ModelAndView mv = new ModelAndView();
        mv.setView(new MappingJackson2JsonView());
        mv.addObject("role", role);
        return mv;
    }


    /**
     * 使用RedirectAttributes进行角色插入并重定向，展示如何在重定向中携带额外信息。
     * @param ra RedirectAttributes接口，用于在重定向中添加闪现属性，SpringMVC会自动初始化它
     * @param roleName 角色名称
     * @param note 角色备注
     * @return 重定向到角色信息页面的字符串路径。
     */
    @RequestMapping("/role/insert3")
    public String insertRole3(RedirectAttributes ra, String roleName, String note) {
        Role role = new Role(roleName, note);
        roleService.insertRole(role);
        ra.addFlashAttribute("role", role);
        return "redirect:./info2";
    }

}
